//
// Created by zerax on 2020/10/23.
//

#include "my_game.hh"

#include <glm/glm.hpp>
#include <glm/ext.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include <file_io.hh>
#include <shader_manager.hh>

#include "config.hh"

using namespace std;

using glm::vec3;
using glm::vec2;

MyGame myGame;
Game* entry = &myGame;

bool MyGame::init() {
    if (!Game::init()) {
        return false;
    }

    vector<vec3> shape = {
            vec3(-0.5f, -0.5f, 0.0f),
            vec3(-0.5f, 0.5f, 0.0f),
            vec3(0.5f, 0.5f, 0.0f),
            vec3(0.5f, -0.5f, 0.0f),
    };

    //  0, 0 --------------- 1, 0
    //   |                    |
    //   |                    |
    //   |                    |
    //   |                    |
    //   |                    |
    //   |                    |
    //  0, 1---------------- 1, 1
    vector<vec2> uvs = {
            vec2(0.0f, 1.0f),
            vec2(0.0f, 0.0f),
            vec2(1.0f, 0.0f),
            vec2(1.0f, 1.0f)
    };

    vector<GLuint> triangles = {
            0, 1, 2,
            2, 3, 0
    };

    vao = VertexArrayBuilder(0, shape)
            .withTexCoords(1, uvs)
            .withTriangles(triangles)
            .calculateNormal(2)
            .build(VertexArrayType::Static);

    auto shaderMgr = ShaderManager::getInstance();
    shaderMgr->loadShaderFromFile("test", "../Shaders/test_vert.glsl", "../Shaders/test_frag.glsl");

    auto* img = SDL_ConvertSurfaceFormat(SDL_LoadBMP("../Assets/dummy.bmp"), SDL_PIXELFORMAT_RGB24, 0);;


    if (img == nullptr) {
        SDL_Log("%s\n", SDL_GetError());
        return false;
    }

    texture = Texture(img->w, img->h, img->pixels);
    texture.setBindPoint("tex", 0);

    proj = glm::perspective(45.0f, float(APP_WINDOW_WIDTH) / APP_WINDOW_HEIGHT, 0.001f, 500.0f);

    SDL_FreeSurface(img);

    setOnMouseClick([this](int mouse) {
        lockMouse = true;
        SDL_ShowCursor(SDL_DISABLE);
    });

    return true;
}

void MyGame::update() {
    auto* keyMap = SDL_GetKeyboardState(nullptr);

    int x, y;
    SDL_GetMouseState(&x, &y);
    int hw = APP_WINDOW_WIDTH / 2;
    int hh = APP_WINDOW_HEIGHT / 2;

    if (keyMap[SDL_SCANCODE_ESCAPE]) {
        lockMouse = false;
        SDL_ShowCursor(SDL_ENABLE);
    }

    if (lockMouse) {
        cam.moveYawPitch(float(x - hw) * 30.0f * getDeltaTime(), float(y - hh) * -30.0f * getDeltaTime());
        wrapMouseInWindow(APP_WINDOW_WIDTH / 2, APP_WINDOW_HEIGHT / 2);
    }

    if (keyMap[SDL_SCANCODE_W]) {
        cam.moveForward(2.0f * getDeltaTime());
    } else if (keyMap[SDL_SCANCODE_S]) {
        cam.moveForward(-2.0f * getDeltaTime());
    }

    if (keyMap[SDL_SCANCODE_A]) {
        cam.moveRight(-2.0f * getDeltaTime());
    } else if (keyMap[SDL_SCANCODE_D]) {
        cam.moveRight(2.0f * getDeltaTime());
    }

    if (keyMap[SDL_SCANCODE_UP]) {
        cam.moveZoom(1);
    } else if (keyMap[SDL_SCANCODE_DOWN]) {
        cam.moveZoom(-1);
    }


    i += 1.0f;
    glm::mat4 model(1.0f);
    model = glm::rotate(model, glm::radians(90.0f), glm::vec3(1.0f, 0.0f, 0.0f));
    model = glm::scale(model, vec3(10.0f));

    glClearColor(1.0, 1.0, 1.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);



    auto program = ShaderManager::getInstance()->getShader("test");
    program->use();
    program->setUniform("proj", proj);
    program->setUniform("view", cam.getMatrix());
    program->setUniform("model", model);
    program->setUniform("cameraPos", cam.getPosition());
    texture.bind(*program);
    vao.draw();
}
